package com.ling.tools.login.config;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.DefaultAdvisorChainFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * File Name: ShrioConfig
 * Date: 2020/2/6 15:08
 * Author: liangling
 * Description
 */
@Configuration
public class ShrioConfig {





//     /**
//      * @author Ling
//      * @Param
//      * @Date 2020-04-02 11:09
//      * @Description  用来管理shrio bean生命周期
//      * @return
//      */
//    @Bean("lifecycleBeanPostProcessor")
//    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
//        return new LifecycleBeanPostProcessor();
//    }

     /**
      * @author Ling
      * @Param
      * @Date 2020-04-02 11:11
      * @Description 在ApplicationContext读取所有的Bean配置信息后，这个类扫描上下文，寻找所有的Advistor(通知器），将他应用到所有符合切入点的Bean中
      * DependsOn是控制bean实例化顺序，在这里必须先使用lifecycleBeanPostProcessor用来初始化，再进行扫描
      * @return
      */
//    @Bean
////    @DependsOn("lifecycleBeanPostProcessor")
//    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
//        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
//        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
//        return advisorAutoProxyCreator();
//    }



    /**
     *添加shrio内置过滤器，可以实现权限相关的拦截器
     * 常用的过滤器
     *     anon:无需认证（登陆）即可访问
     *     authc: 必须认证才可以访问（登陆）
     *     user: 如果使用rememberMe的功能可以直接访问
     *     perms: 该资源必须得到资源权限才可以访问
     *     role: 该资源必须的到角色权限才可以访问
     *
     */
    @Bean(name = "shrioFilter")
    public ShiroFilterFactoryBean shrioFilter(SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //如果不设置默认会自动寻找web工程根目录下的“login.jsp”页面
//        shiroFilterFactoryBean.setLoginUrl("/login");
        //设置未授权界面
//        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        //设置登陆成功之后要跳转的链接
//        shiroFilterFactoryBean.setSuccessUrl("/index");
        //LinkedHashMap是有序的
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        //anon:所有url都可以匿名访问不需要认证  authc:所有指定url必须通过认证才可以访问
//        filterChainDefinitionMap.put("/login","anon");
//        //设置退出过滤器，退出过程shrio已经实现
//        filterChainDefinitionMap.put("/logout","logout");
//        filterChainDefinitionMap.put("/","anon");
//        filterChainDefinitionMap.put("/admin/**","authc");
//        filterChainDefinitionMap.put("/swagger-ui.html/**", "anon");
//        filterChainDefinitionMap.put("/user/**","authc");
        //authc:所有URL都必须认证通过才可以访问；anon:所有URL都可以匿名访问
        filterChainDefinitionMap.put("/**","anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }




     /**
       * 安全管理器
       */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(myRealm());
        return defaultWebSecurityManager;
    }




    /**
     * 凭证匹配器
     * （由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     *  所以我们需要修改下doGetAuthenticationInfo中的代码;
     * ）
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();

        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数，比如散列两次，相当于 md5(md5(""));

        return hashedCredentialsMatcher;
    }

    @Bean
    public MyRealm myRealm(){
        MyRealm myRealm = new MyRealm();
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return myRealm;
    }

    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }





        @Bean
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);

            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
       /* filterChainDefinitionMap.put("/", "anon");

        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/blogFile/**", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/register", "anon");
        filterChainDefinitionMap.put("/**", "authc"); */

            //filterChainDefinitionMap.put("/**/create", "authc");
            //filterChainDefinitionMap.put("/**/update", "authc");
            //filterChainDefinitionMap.put("/**/delete", "authc");
            //filterChainDefinitionMap.put("/upload", "authc");
            //filterChainDefinitionMap.put("/users/currentUser", "authc");

            filterChainDefinitionMap.put("/**", "anon");

            //返回json数据，由前端跳转
            shiroFilterFactoryBean.setLoginUrl("/handleLogin");

            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
            return shiroFilterFactoryBean;
        }



//        @Bean
//        public SecurityManager securityManager(OAuthRealm oAuthRealm, SessionManager sessionManager) {
//            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//            securityManager.setRealm(oAuthRealm);
//            securityManager.setSessionManager(sessionManager);
//            // 自定义缓存实现 使用redis
//            //securityManager.setCacheManager(cacheManager());
//            return securityManager;
//        }
//
//        @Bean
//        public SessionManager sessionManager(OAuthSessionDAO authSessionDAO) {
//            OAuthSessionManager oAuthSessionManager = new OAuthSessionManager();
//            oAuthSessionManager.setSessionDAO(authSessionDAO);
//            return oAuthSessionManager;
//        }
//
//
//        @Bean
//        public OAuthSessionDAO authSessionDAO(RedisManager redisManager) {
//            OAuthSessionDAO authSessionDAO = new OAuthSessionDAO();
//            authSessionDAO.setRedisManager(redisManager);
//            return authSessionDAO;
//        }


        @Bean
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
















}
